﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Virgee.Common.Interfaces;

namespace Virgee.Common.Serializers
{
    public class XmlSerializer : ISerializer
    {
        /// <summary>
        /// An XML serializer that wraps <see cref="T:System.Xml.Serialization.XmlSerializer"/>
        /// </summary>
        public XmlSerializer()
        {
            // This space intentionally left blank
        }

        /// <summary>
        /// Serializes the given input object to xml format.
        /// </summary>
        /// <typeparam name="T">The input type.</typeparam>
        /// <param name="input">The input value.</param>
        /// <param name="additionalInfo">Used to pass additional information that may be required by the serializer to serialize the input object.</param>
        /// <returns>Returns a <see cref="T:System.String"/> instance in xml format representing the serialized object.</returns>
        public virtual string Serialize<T>(T input, IDictionary<string, object> additionalInfo = null) where T : class
        {
            System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
            using (MemoryStream memoryStream = new MemoryStream())
            {
                xs.Serialize(memoryStream, input);
                memoryStream.Seek(0, SeekOrigin.Begin);
                using (StreamReader streamReader = new StreamReader(memoryStream))
                {
                    return streamReader.ReadToEnd();
                }
            }
        }

        /// <summary>
        /// Deserializes the given <see cref="T:System.String"/> in xml format to an instance of an object of the specified type.
        /// </summary>
        /// <typeparam name="T">The type.</typeparam>
        /// <param name="input">The xml <see cref="T:System.String"/> input.</param>
        /// <param name="additionalInfo">Used to pass additional information that may be required by the serializer to deserialize the input <see cref="T:System.String"/>.</param>
        /// <returns>Returns an instance of the specified type deserialized from the given <see cref="T:System.String"/> in xml format.</returns>
        public virtual T Deserialize<T>(string input, IDictionary<string, object> additionalInfo = null) where T : class
        {
            System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
            using (StringReader sr = new StringReader(input))
            {
                return (T)xs.Deserialize(sr);
            }
        }

        /// <summary>
        /// Returns XML media type.
        /// </summary>
        public virtual string MediaType
        {
            get { return "application/xml"; }
        }
    }
}
